#include "ProceduralStableHeaders.h"
#include "ProceduralOperator.h"

namespace Procedural
{
void OperatorManager::deserialize(string fileName)
	{
		using namespace Ogre;
		Utils::log("Parsing file " + fileName);
		string line;
		ifstream f(fileName);
		bool isInOperator = false;
		OperatorDefinition* currentOperatorDef = 0;
		Operator* currentOperator = 0;
		string currentOperatorInstanceName;
		while ( f.good() )
		{
			getline(f,line);
			//Utils::log("read line " + line);
			std::vector<string> tokens = tokenize(line);
			if (tokens.size()>0)
			{
				if (!isInOperator)
				{
					if (tokens.size()>=2)
					{
						if (mOperators.find(tokens[0])!=mOperators.end())
						{
							Utils::log("Operator " + tokens[0] + " detected with id " + tokens[1]);
							isInOperator = true;
							currentOperatorDef = &mOperators[tokens[0]];
							currentOperator = mOperators[tokens[0]].defaultInstance->clone();
							currentOperatorInstanceName = tokens[1];
						}						
					}
				} 
				else 
				{
					if (line.find("{")!=string::npos)
					{//fine then
					} else
					if (line.find("}")!=string::npos)
					{
						isInOperator = false;	
						currentOperator->buildOutput();
						TriangleBuffer* tb = (TriangleBuffer*)currentOperator->outputCache;
						tb->transformToMesh(currentOperatorInstanceName);
					} else {
						if (tokens.size()>=2)
						{
							Utils::log("attribute " + tokens[0] + " value " + tokens[1]);
							if (currentOperatorDef->mInputParamList.find(tokens[0]) != currentOperatorDef->mInputParamList.end())
							{
							switch (currentOperatorDef->mInputParamList[tokens[0]].mType)
							{
							case BT_REAL:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseReal(tokens[1]));
								break;
							case BT_UINT:
							case BT_USHORT:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseUnsignedInt(tokens[1]));
								break;
							case BT_INT:							
							case BT_SHORT:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseInt(tokens[1]));
								break;
							case BT_ULONG:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseUnsignedLong(tokens[1]));
								break;
							case BT_LONG:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseLong(tokens[1]));
								break;
							case BT_STRING:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, tokens[1]);
								break;
							case BT_BOOL:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseBool(tokens[1]));
								break;			
							case BT_VEC2:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseVector2(tokens[1]));
								break;
							case BT_VEC3:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseVector3(tokens[1]));
								break;
							case BT_VEC4:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseVector4(tokens[1]));
								break;
							case BT_QUAT:
								currentOperatorDef->setInputParam(tokens[0], currentOperator, StringConverter::parseQuaternion(tokens[1]));
								break;
							default:
								Utils::log("No behaviour defined for this type : " + StringConverter::toString(currentOperatorDef->mInputParamList[tokens[0]].mType));
								break;
							}
							}
							else
							{
								Utils::log("Unknown attribute " + tokens[0] + " for this operator");
							}
						}
					}
				}				
			}
		}

		f.close();
	}
}